package com.Sony.TemplateGame;

import org.anddev.andengine.entity.layer.tiled.tmx.TMXLayer;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXLoader;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXObject;
import org.anddev.andengine.entity.layer.tiled.tmx.TMXObjectGroup;
import org.anddev.andengine.entity.layer.tiled.tmx.util.exception.TMXLoadException;
import org.anddev.andengine.entity.primitive.Rectangle;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.shape.Shape;
import org.anddev.andengine.extension.physics.box2d.FixedStepPhysicsWorld;
import org.anddev.andengine.extension.physics.box2d.PhysicsFactory;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.util.Debug;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.FixtureDef;


/**
 *	Class untuk membuat dan mengatur scene
 *	@author sony wirawan
 **/
public class GameScene 
{
	private TemplateGameActivity core;
	private SceneUserData scene_userdata;
	private ObjectUserData item_userdata;
	private ObjectUserData wrap_userdata;
	
	private Scene mScene;
	private Rectangle rectangle;
	private FixedStepPhysicsWorld mPhysicsWorld;
	private Body mPlayerBody;
	
	private String map_name;
	private String scene_code;

	
	/**
	 *	Constructor item
	 *	@param BA = context yang digunakan
	 *	@author sony wirawan
	 **/
	public GameScene
	(	TemplateGameActivity template,
		String name,
		String code
	) 
	{	// TODO Auto-generated constructor stub
		this.core = template;
		this.map_name = name;
		this.scene_code = code;
		
		this.mScene = new Scene();
		this.mPhysicsWorld = new FixedStepPhysicsWorld(30, new Vector2(0, 0), false, 8, 1);
		this.rectangle = new Rectangle(0, 0, 0, 0);
		this.mScene.setUserData(this.scene_code);

		// register physics update handler
		this.mScene.registerUpdateHandler(this.mPhysicsWorld);
		
		// create controller
		this.mScene.setChildScene(this.core.player.mDigitalOnScreenControl);
		
		// create player
		this.mPlayerBody = this.core.player.loadPlayer(this.mPhysicsWorld);
		
		// create map
		this.createMap();
		
		// attach map
		this.mScene.attachChild(this.rectangle);
		
		// load contact and update
		this.core.loadContact(this.mPhysicsWorld);
		this.core.loadUpdate(this.mScene, this.mPlayerBody);
		
		// set userdata
		this.scene_userdata = new SceneUserData(this.map_name, this.scene_code, this.mPlayerBody);
		this.mScene.setUserData(this.scene_userdata);
		
		// insert to vector of scene
		this.core.vector_scene.add(this.mScene);
	}
	
	
	/**
	 *	Method untuk membangun map
	 *	@author sony wirawan
	 **/
	public void createMap()
	{	// Load the TMX map
		try 
		{	this.core.tmxLoader = new TMXLoader
			(	this.core,
				this.core.getEngine().getTextureManager(),
				TextureOptions.BILINEAR_PREMULTIPLYALPHA,
				null
			);
			
			this.core.mTMXTiledMap = this.core.tmxLoader.loadFromAsset(this.core, this.map_name); 
		} 
		catch (final TMXLoadException tmxle) 
		{	Debug.e(tmxle); }		
		
		// Add the non-object layers to the scene
		for (int i = 0; i < this.core.mTMXTiledMap.getTMXLayers().size(); i++)
		{	TMXLayer layer = this.core.mTMXTiledMap.getTMXLayers().get(i);
			if (!layer.getTMXLayerProperties().containsTMXProperty("wall", "true"))
			this.rectangle.attachChild(layer);
		}
		
		// Make the camera not exceed the bounds of the TMXEntity.
		this.createBound();
		
		// Read in the unwalkable blocks from the object layer and create boxes for each
		this.createObject();
	}


	/**
	 *	Method untuk membuat pagar / batas dari map scene
	 *	@author sony wirawan
	 **/
	private void createBound()
	{	// TODO Auto-generated method stub
		final TMXLayer tmxLayer = this.core.mTMXTiledMap.getTMXLayers().get(0);
		this.core.mBoundChaseCamera.setBounds(0, tmxLayer.getWidth(), 0, tmxLayer.getHeight());
		this.core.mBoundChaseCamera.setBoundsEnabled(true);
		
		// create boundary shape
		final Shape bottom = new Rectangle(0, tmxLayer.getHeight() - 2, tmxLayer.getWidth(), 2);
		bottom.setVisible(false);
		final Shape top = new Rectangle(0, 0, tmxLayer.getWidth(), 2);
		top.setVisible(false);
		final Shape left = new Rectangle(0, 0, 2, tmxLayer.getHeight());
		left.setVisible(false);
		final Shape right = new Rectangle(tmxLayer.getWidth() - 2, 0, 2, tmxLayer.getHeight());
		right.setVisible(false);

		// create boundary body
		final FixtureDef wallFixtureDef = PhysicsFactory.createFixtureDef(0, 0, 1f);
		PhysicsFactory.createBoxBody(this.mPhysicsWorld, bottom, BodyType.StaticBody, wallFixtureDef);
		PhysicsFactory.createBoxBody(this.mPhysicsWorld, top, BodyType.StaticBody, wallFixtureDef);
		PhysicsFactory.createBoxBody(this.mPhysicsWorld, left, BodyType.StaticBody, wallFixtureDef);
		PhysicsFactory.createBoxBody(this.mPhysicsWorld, right, BodyType.StaticBody, wallFixtureDef);
		
		// attach boundary object to parent
		this.rectangle.attachChild(bottom);
		this.rectangle.attachChild(top);
		this.rectangle.attachChild(left);
		this.rectangle.attachChild(right);
	}

	
	/**
	 *	Method untuk membuat dan mengatur obyek-obyek yang terdapat pada scene
	 *	@author sony wirawan
	 **/
	private void createObject()
	{	// TODO Auto-generated method stub
		// Loop through the object groups
		 for(final TMXObjectGroup group: this.core.mTMXTiledMap.getTMXObjectGroups()) 
		 {	 
			 // create wall
			 if(group.getTMXObjectGroupProperties().containsTMXProperty("wall", "true"))
			 {	// This is our "wall" layer. Create the boxes from it
			 	for(final TMXObject object : group.getTMXObjects()) 
			 	{	final Rectangle rect = new Rectangle(object.getX()+4, object.getY()+4,object.getWidth()-8, object.getHeight()-8);
					final FixtureDef boxFixtureDef = PhysicsFactory.createFixtureDef(0, 0, 1f);
					PhysicsFactory.createBoxBody(this.mPhysicsWorld, rect, BodyType.StaticBody, boxFixtureDef);
					rect.setColor(100, 100, 100);
					rect.setVisible(false);
					this.rectangle.attachChild(rect);
				 }
			 }
			 
			 // create special point
			 else if(group.getTMXObjectGroupProperties().containsTMXProperty("point", "true"))
			 {	 
				 for(final TMXObject object : group.getTMXObjects())
				 {	// set item point
					 if(object.getName().equals("item"))
					 {	// badge item
						if(object.getTMXObjectProperties().containsTMXProperty("badge", "true"))
						{	// create badge item
							Body mItemBody = this.core.gameItem.createItem
							(	this.mPhysicsWorld,
								"badge.png",
								"badge"
							);
						
							// set badge item position
							this.core.vector_item.add(mItemBody);
							mItemBody.setTransform
							(	(object.getX()+16)/32,
								(object.getY()+16)/32,
								0
							);
							
							// set badge item userdata
							this.item_userdata = (ObjectUserData) mItemBody.getUserData();
							this.rectangle.attachChild(this.item_userdata.item_sprite);
						}
						
						// box item
						else if(object.getTMXObjectProperties().containsTMXProperty("box", "true"))
						{	// create box item
							Body mItemBody = this.core.gameItem.createItem
							(	this.mPhysicsWorld,
								"box.png",
								"box"
							);
						
							// set box item position
							this.core.vector_item.add(mItemBody);
							mItemBody.setTransform
							(	(object.getX()+16)/32,
								(object.getY()+16)/32,
								0
							);
							
							// set box item userdata
							this.item_userdata = (ObjectUserData) mItemBody.getUserData();
							this.rectangle.attachChild(this.item_userdata.item_sprite);
						}
						
						// face item
						else if(object.getTMXObjectProperties().containsTMXProperty("face", "true"))
						{	// create face item
							Body mItemBody = this.core.gameItem.createItem
							(	this.mPhysicsWorld,
								"face_box.png",
								"face"
							);
						
							// set face item position
							this.core.vector_item.add(mItemBody);
							mItemBody.setTransform
							(	(object.getX()+16)/32,
								(object.getY()+16)/32,
								0
							);
							
							// set face item userdata
							this.item_userdata = (ObjectUserData) mItemBody.getUserData();
							this.rectangle.attachChild(this.item_userdata.item_sprite);
						}
					 }
					 
					 // set the wrap / exit point
					 else if(object.getName().equals("wrap"))
					 {	// set the exit point
						final Shape exit = new Rectangle
						(	object.getX()+8, 
							object.getY()+8,
							object.getWidth()-16,
							object.getHeight()-16
						);
						/* Create A spinning rectangle and a line. */
						exit.setVisible(false);
						exit.setColor(100, 100, 0);
						final FixtureDef wrapFixtureDef = PhysicsFactory.createFixtureDef(0, 0, 0.5f);
						Body exit_point = PhysicsFactory.createBoxBody(this.mPhysicsWorld, exit, BodyType.StaticBody, wrapFixtureDef);
						
						
						if(object.getTMXObjectProperties().containsTMXProperty("scene0", "true"))
						{	// set userdata
							this.wrap_userdata = new ObjectUserData("exit", "scene0");
							exit_point.setUserData(this.wrap_userdata);
						}
						else if(object.getTMXObjectProperties().containsTMXProperty("scene1", "true"))
						{	// set userdata
							this.wrap_userdata = new ObjectUserData("exit", "scene1");
							exit_point.setUserData(this.wrap_userdata);							
						}
						else if(object.getTMXObjectProperties().containsTMXProperty("scene2", "true"))
						{	// set userdata
							this.wrap_userdata = new ObjectUserData("exit", "scene2");
							exit_point.setUserData(this.wrap_userdata);
						}

						this.rectangle.attachChild(exit);
					 }
				 }
			 }
		 }
	}
}
